using QFramework;
using System.Collections;
using UnityEngine;
using M13.GameSystem;
using M13.Base;
using System;
using Cysharp.Threading.Tasks;
using UnityEngine.Serialization;
using Physics = UnityEngine.Physics;

namespace M13.Game
{
    public class CameraControler : MonoBehaviour, IController, ICanSendEvent
    {
        [FormerlySerializedAs("_cameraFollowingSensitivity")]
        [SerializeField]
        [Range(0f, 1f)]
        private float cameraFollowingSensitivity;

        [FormerlySerializedAs("_cameraRotationTime")] [SerializeField]
        private float cameraRotationTime;

        private bool _isRototaing;

        private IInputCtrlSystem _inputCtrlSystem;

        [FormerlySerializedAs("_playerPos")] [SerializeField]
        private Vector3 playerPos;

        [FormerlySerializedAs("_mouseTarget")] [SerializeField] private Vector3 mouseTarget;

        private MaxFramePerSecond _maxFramePerSecond = new MaxFramePerSecond();

        private Quaternion _target;

        private void Awake()
        {
            this.GetModel<ICameraModal>().CameraPos.Value = transform.position;
            this.GetModel<ICameraModal>().CameraRot.Value = transform.rotation;
            this.GetModel<ICameraModal>().MouseTarget.Value = mouseTarget;
        }

        private void Start()
        {
            _inputCtrlSystem = this.GetSystem<IInputCtrlSystem>();

            this.GetModel<IPlayerModal>().PlayerPos.RegisterWithInitValue(e => ReceivePlayerPos(e));
            this.RegisterEvent<CameraLeftRotButton>(e => { CameraLeftRot(e.cameraLeftRotInput); });
            this.RegisterEvent<CameraRightRotButton>(e => { CameraRightRot(e.cameraRightRotInput); });

            
        }
        private void Update()
        {
            this.GetModel<ICameraModal>().CameraPos.Value = transform.position;
            this.GetModel<ICameraModal>().CameraRot.Value = transform.rotation;
            this.GetModel<ICameraModal>().MouseTarget.Value = mouseTarget;

            transform.rotation = Quaternion.Slerp(transform.rotation, _target, 25 * Time.deltaTime);
        }
        private void LateUpdate()
        {
            
            transform.position = Vector3.Lerp(
                transform.position,
                playerPos + (new Vector3(mouseTarget.x, transform.position.y, mouseTarget.z) - playerPos) * cameraFollowingSensitivity,
                 Time.deltaTime * 10f);
            
        }
       
        void FixedUpdate()
        {
            if ((int)_maxFramePerSecond != 0)
                Application.targetFrameRate = (int)_maxFramePerSecond;


            if (Camera.main != null)
            {
                Ray ray = Camera.main.ScreenPointToRay(_inputCtrlSystem.CursorPosInput);
                RaycastHit hitInfo;
                float dis;
                Plane hitPlane = new Plane(Vector3.up, playerPos + new Vector3(0, 0.9f, 0));
            
                if (Physics.Raycast(ray, out hitInfo))
                {
                    // this.GetModel<ICameraModal>().ItemName.Value = hitInfo.transform.gameObject.name;
                    //  if(_inputCtrlSystem.Execute0Input != 0)
                    //      if (hitInfo.transform.gameObject.CompareTag("Chunk"))
                    //      {
                    //          this.GetModel<ICameraModal>().RayHitedChunkPos.Value = hitInfo.transform.position;
                    //          PlayerExecute0Event evt = new PlayerExecute0Event();
                    //          evt.item = this.GetModel<IPlayerModal>().PlayerHoldingItem.Value;
                    //          evt.execute0Position = hitInfo.transform.position;
                    //          this.SendEvent(evt);
                    //          Debug.Log(this.GetModel<ICameraModal>().RayHitedChunkPos.Value);
                    //      }
                    //  if(_inputCtrlSystem.Execute1Input != 0)
                    //      if (hitInfo.transform.gameObject.CompareTag("Chunk"))
                    //      {
                    //          this.GetModel<ICameraModal>().RayHitedChunkPos.Value = hitInfo.transform.position;
                    //          PlayerExecute1Event evt = new PlayerExecute1Event();
                    //          evt.item = this.GetModel<IPlayerModal>().PlayerHoldingItem.Value;
                    //          evt.execute1Position = hitInfo.transform.position;
                    //          this.SendEvent(evt);
                    //          Debug.Log(this.GetModel<ICameraModal>().RayHitedChunkPos.Value);
                    //      }
                }
            
                if (hitPlane.Raycast(ray, out dis))
                {
                    mouseTarget = this.GetModel<ICameraModal>().MouseTarget.Value = ray.GetPoint(dis);
                }
            }
        }

        private void ReceivePlayerPos(Vector3 playerPos)
        {
            this.playerPos = playerPos;
        }

        void CameraLeftRot(float e)
        {
            if (e == 1f && !_isRototaing)
            {
                DelayTime();
                _target = Quaternion.Euler(0, 45 + transform.rotation.eulerAngles.y, 0);
            }
        }
        void CameraRightRot(float e)
        {
            if (e == 1f && !_isRototaing)
            {
                DelayTime();
                _target = Quaternion.Euler(0, -45 + transform.rotation.eulerAngles.y, 0);
            }
        }

        private async void DelayTime()
        {
            _isRototaing = true;
            await UniTask.WaitForSeconds(0.25f);
            _isRototaing = false;
        }

        public Vector3 GetMouseTarget()
        {
            return mouseTarget;
        }

        public IArchitecture GetArchitecture()
        {
            return GameArchitecture.Interface;
        }
    }
    public enum MaxFramePerSecond
    {
        Unlimited = 500,
        F144 = 144,
        F72 = 72,
        F60 = 60,
        F24 = 24

    }
}